/******************************************************************************
* 文件名称: fs.h
* 内容摘要: 文件系统头文件
* 创建者の: 孔佳伟
* 个人主页: https://gitee.com/thin-wind/jump
* 修改记录: 
******************************************************************************/

#ifndef __FS_H_
#define __FS_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <common.h>
#include <hd.h>
#include <memory.h>
#include <list.h>


#define SYS_SEC_NUM         (10*1024*1024/SEC_SIZE)                 // 人为规定硬盘前 10M 空间用于存放系统本身，10M 后才用于文件系统
#define FS_SEC_NUM          (GetHardDiskSectors() - SYS_SEC_NUM)    // 文件系统管理的硬盘扇区数 = 硬盘总扇区数 - 操作系统本身占用的扇区数

// 定义文件系统需要的接口函数，文件读写以扇区为单位，顾 buf 大小为 SEC_SIZE
#define FS_WRITE(sn, buf)   HardDiskWrite((sn)+SYS_SEC_NUM, (U08 *)(buf))
#define FS_READ(sn, buf)    HardDiskRead((sn)+SYS_SEC_NUM, (U08 *)(buf))
#define FS_MALLOC(size)     Malloc((size))
#define FS_FREE(p)          Free((p))


// 文件类型
typedef enum E_F_TYPE
{
    E_FILE,                         // 文件
    E_DIR                           // 文件夹
} E_F_TYPE;

// 记录一个文件的基本信息
typedef struct FILE_ENTRY
{
    U08         name[32];           // 文件名
    U32         fileBegin;          // 文件的第一个扇区号
    U32         fileNum;            // 文件占用的扇区数
    U32         lastBytes;          // 最后一个扇区中的有效数据字节数
    E_F_TYPE    type;               // 文件类型（文件/文件夹）
    U32         inSecIdx;           // FILE_ENTRY 这个数据结构本身也要存储在硬盘上，inSecIdx 为 FILE_ENTRY 这个数据结构本身存储在扇区号
    U32         inSecOff;           // FILE_ENTRY 这个数据结构本身也要存储在硬盘上，inSecOff 为 FILE_ENTRY 这个数据结构本身存储在扇区中的偏移量
    U32         resered[2];         // 保留
} FILE_ENTRY;

typedef struct FILE_DESC
{
    LIST_NODE   node;
    FILE_ENTRY  fe;
    U32         secIdx;             // 文件数据链表节点偏移
    U32         offset;             // 用于记录文件读写位置
    U08         changed;            // 数据是否被修改
    U08         catch[SEC_SIZE];    // 数据缓冲区
} FILE_DESC;

/******************************************************************************
* 函数名称: E_RET FsInit(void)
* 功能说明: 文件系统初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET FsInit(void);

/******************************************************************************
* 函数名称: E_RET SYS_CreatFileInRoot(const U08* name)
* 功能说明: 在根目录 root 下创建一个文件
* 输入参数: const U08* name      --要创建的文件名
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_CreatFileInRoot(const U08* name);

/******************************************************************************
* 函数名称: E_RET DeleteFileInRoot(const U08* name)
* 功能说明: 在根目录 root 下删除一个文件
* 输入参数: const U08* name      --要删除的文件名
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_DeleteFileInRoot(const U08* name);

/******************************************************************************
* 函数名称: E_RET RenameFileInRoot(const U08* old, const U08* new)
* 功能说明: 文件重命名
* 输入参数: const U08* old          --旧文件名
    　　　　const U08* new          --新文件名
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_RenameFileInRoot(const U08* old, const U08* new);

/******************************************************************************
* 函数名称: FILE_DESC* FileOpen(const U08* name)
* 功能说明: 打开文件
* 输入参数: const U08* name          --文件名
* 输出参数: 无
* 函数返回: FILE_DESC*               --文件描述符
* 其它说明: 无
******************************************************************************/
FILE_DESC* SYS_FileOpen(const U08* name);

/******************************************************************************
* 函数名称: E_RET FileClose(FILE_DESC* fd)
* 功能说明: 关闭文件
* 输入参数: FILE_DESC* fd       --文件描述符
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_FileClose(FILE_DESC* fd);

/******************************************************************************
* 函数名称: U32 FileWrite(FILE_DESC* fd, U08* buf, U32 len)
* 功能说明: 向文件中写入数据
* 输入参数: FILE_DESC* fd       --文件描述符
    　　　　U08* buf            --写入的数据缓冲区首地址
    　　　　U32 buf             --要写入的数据长度
* 输出参数: 无
* 函数返回: 成功写入文件的数据长度
* 其它说明: 无
******************************************************************************/
U32 SYS_FileWrite(FILE_DESC* fd, U08* buf, U32 len);

/******************************************************************************
* 函数名称: U32 FileRead(FILE_DESC* fd, U08* buf, U32 len)
* 功能说明: 从文件中读取数据
* 输入参数: FILE_DESC* fd       --文件描述符
    　　　　U08* buf            --数据读入的缓冲区首地址
    　　　　U32 buf             --要读取的数据长度
* 输出参数: 无
* 函数返回: 成功读取文件的数据长度
* 其它说明: 无
******************************************************************************/
U32 SYS_FileRead(FILE_DESC* fd, U08* buf, U32 len);

/******************************************************************************
* 函数名称: U32 GetFileLen(FILE_DESC* fd)
* 功能说明: 获取文件数据大小
* 输入参数: FILE_DESC* fd       --文件描述符
* 输出参数: 无
* 函数返回: 文件数据大小
* 其它说明: 无
******************************************************************************/
U32 SYS_GetFileLen(FILE_DESC* fd);

/******************************************************************************
* 函数名称: U32 FileTell(FILE_DESC* fd)
* 功能说明: 得到文件当前读写位置指针相对于文件首的偏移字节数
* 输入参数: FILE_DESC* fd       --文件描述符
* 输出参数: 无
* 函数返回: 文件当前读写位置指针相对于文件首的偏移字节数
* 其它说明: 无
******************************************************************************/
U32 SYS_FileTell(FILE_DESC* fd);

/******************************************************************************
* 函数名称: E_RET FileSeek(FILE_DESC* fd, U32 pos)
* 功能说明: 设置文件当前读写指针位置
* 输入参数: FILE_DESC* fd       --文件描述符
    　　　　U32 pos             --读写指针设置位置
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SYS_FileSeek(FILE_DESC* fd, U32 pos);


#ifdef __cplusplus
}
#endif

#endif

